const onceCall = require("./template.js")

function testOnceCall() {
  console.log(
    "1. 基本功能:",
    (() => {
      let count = 0
      const resultValue = null
      const fn = () => {
        count++
        return resultValue
      }
      const onceFn = onceCall(fn)

      const result1 = onceFn()
      const result2 = onceFn()

      return count === 1 && result1 === resultValue && result2 === resultValue
    })()
  )

  console.log(
    "2. 返回值一致:",
    (() => {
      const fn = () => Math.random()
      const onceFn = onceCall(fn)

      const result1 = onceFn()
      const result2 = onceFn()

      return result1 === result2
    })()
  )

  console.log(
    "3. 带参数的函数:",
    (() => {
      let lastArgs = null
      const fn = (a, b) => {
        lastArgs = [a, b]
        return a + b
      }
      const onceFn = onceCall(fn)

      const result1 = onceFn(1, 2)
      onceFn(3, 4) // 这次调用应该被忽略

      return result1 === 3 && lastArgs[0] === 1 && lastArgs[1] === 2
    })()
  )

  console.log(
    "4. 副作用只执行一次:",
    (() => {
      let sideEffect = 0
      const fn = () => {
        sideEffect = 999
        return "done"
      }
      const onceFn = onceCall(fn)

      onceFn()
      sideEffect = 0 // 重置
      onceFn() // 再次调用，不应该修改sideEffect

      return sideEffect === 0
    })()
  )

  console.log(
    "5. this上下文保持:",
    (() => {
      const obj = {
        value: 42,
        getValue: function () {
          return this.value
        }
      }

      const onceGetValue = onceCall(obj.getValue.bind(obj))
      return onceGetValue() === 42 && onceGetValue() === 42
    })()
  )

  console.log(
    "6. 异常处理:",
    (() => {
      let callCount = 0
      const fn = () => {
        callCount++
        if (callCount === 1) {
          throw new Error("first call error")
        }
        return "success"
      }
      const onceFn = onceCall(fn)

      try {
        onceFn()
      } catch (e) {
        // 第一次调用抛异常
      }

      // 第二次调用应该仍然抛异常（因为函数只执行一次）
      try {
        onceFn()
        return false // 如果没抛异常，测试失败
      } catch (e) {
        return callCount === 1 // 确保只调用了一次
      }
    })()
  )

  console.log(
    "7. 多个独立实例:",
    (() => {
      let count1 = 0,
        count2 = 0
      const fn1 = () => {
        count1++
        return "fn1"
      }
      const fn2 = () => {
        count2++
        return "fn2"
      }

      const onceFn1 = onceCall(fn1)
      const onceFn2 = onceCall(fn2)

      onceFn1()
      onceFn1() // 不应该执行
      onceFn2()
      onceFn2() // 不应该执行

      return count1 === 1 && count2 === 1
    })()
  )

  console.log(
    "8. 返回undefined的函数:",
    (() => {
      let executed = false
      const fn = () => {
        executed = true
        // 不返回任何值（即返回undefined）
      }
      const onceFn = onceCall(fn)

      const result1 = onceFn()
      const result2 = onceFn()

      return executed && result1 === undefined && result2 === undefined
    })()
  )

  console.log(
    "9. 复杂对象返回值:",
    (() => {
      const complexObj = { data: [1, 2, 3], nested: { value: "test" } }
      const fn = () => complexObj
      const onceFn = onceCall(fn)

      const result1 = onceFn()
      const result2 = onceFn()

      return (
        result1 === complexObj && result2 === complexObj && result1 === result2
      )
    })()
  )

  console.log(
    "10. 长时间延迟调用:",
    (() => {
      let callTime = null
      const fn = () => {
        callTime = Date.now()
        return "delayed"
      }
      const onceFn = onceCall(fn)

      onceFn()
      const firstCallTime = callTime

      // 模拟延迟后再次调用
      setTimeout(() => {}, 10) // 简单延迟
      onceFn()

      return callTime === firstCallTime // 时间应该没有更新
    })()
  )

  console.log(
    "11. 返回空值undefined:",
    (() => {
      let count = 0
      const resultValue = undefined
      const fn = () => {
        count++
        return resultValue
      }
      const onceFn = onceCall(fn)

      const result1 = onceFn()
      const result2 = onceFn()

      return count === 1 && result1 === resultValue && result2 === resultValue
    })()
  )


  console.log(
    "11. 返回假值false:",
    (() => {
      let count = 0
      const resultValue = false
      const fn = () => {
        count++
        return resultValue
      }
      const onceFn = onceCall(fn)

      const result1 = onceFn()
      const result2 = onceFn()

      return count === 1 && result1 === resultValue && result2 === resultValue
    })()
  )
}

testOnceCall()
